package com.chinaunicom.emergency.action;

import com.alibaba.fastjson.JSONObject;
import com.chinaunicom.emergency.constant.ConstantUtil;
import com.chinaunicom.emergency.model.YjglUser;
import com.chinaunicom.emergency.exception.OAuthException;
import com.chinaunicom.emergency.repository.OauthClientDetailsRepository;
import com.chinaunicom.emergency.repository.UserRoleRepository;
import com.chinaunicom.emergency.repository.UsersRepository;
import com.chinaunicom.emergency.service.RedisService;
import com.chinaunicom.emergency.util.ImageCode;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint;
import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

@Api(tags = {"认证扩展接口"})
@RestController
@Log4j2
@RefreshScope
public class TokenExtendAction extends BaseAction {

    @Autowired
    @Qualifier("consumerTokenServices")
    ConsumerTokenServices consumerTokenServices;

    @Autowired
    private UserRoleRepository userRoleRepository;
    @Autowired
    private UsersRepository usersRepository;
    @Autowired
    TokenStore tokenStore;
    @Autowired
    OauthClientDetailsRepository oauthClientDetailsRepository;

    @Autowired
    CheckTokenEndpoint tokenEndpoint;

    @Autowired
    RedisService redisService;


    @ApiOperation("清除token")
    @DeleteMapping("/oauth/revoke/token")
    public Object revokeToken(@RequestParam(required = false,value = "access_token") String accessToken,
                              @RequestParam(required = false,value = "roleId") String roleId,@RequestParam(required = false,value = "userId") String userId) throws OAuthException {
        if(StringUtils.isAllBlank(accessToken,roleId,userId)){
            throw new OAuthException("access_token或roleId或userId选一");
        }
        boolean flag = false;
        if(StringUtils.isNotBlank(accessToken)){
            flag = consumerTokenServices.revokeToken(accessToken);
            log.info("token移除结果：token : {}, result : {}",accessToken,flag);
        }
        List<String> clientIds = oauthClientDetailsRepository.findClienIds();
        if(StringUtils.isNotBlank(userId)){
            YjglUser user = usersRepository.findYjglUserByPidAndIsSoftDel(userId,0);
            if(null != user ){
                for (String clientId : clientIds){
                    Collection<OAuth2AccessToken> tokenCollection =
                            tokenStore.findTokensByClientIdAndUserName(clientId,user.getUserName());
                    for(OAuth2AccessToken token : tokenCollection){
                        if(null != token && StringUtils.isNotBlank(token.getValue())){
                            flag = consumerTokenServices.revokeToken(token.getValue());
                            log.info("token批量移除结果：clientId :{},userName:{}, token: {} , result : {}",clientId,user.getUserName(),accessToken,flag);
                        }
                    }
                }
            }
        }
        if(StringUtils.isNotBlank(roleId)){
            List<String> userNameList = userRoleRepository.findUserNameByRoleId(roleId);
            for (String clientId : clientIds){
                for (String userName : userNameList){
                    Collection<OAuth2AccessToken> tokenCollection =
                    tokenStore.findTokensByClientIdAndUserName(clientId,userName);
                    for(OAuth2AccessToken token : tokenCollection){
                        if(null != token && StringUtils.isNotBlank(token.getValue())){
                            flag = consumerTokenServices.revokeToken(token.getValue());
                            log.info("token批量移除结果：clientId :{},userName:{},roleId : {} , token: {} , result : {}",clientId,userName,roleId,accessToken,flag);
                        }
                    }
                }

            }
        }
        return success();
    }


    @ApiOperation("第三方系统校验token合法性")
    @GetMapping(value = "/oauth/check_token/outer")
    JSONObject checkToken(@RequestParam("token") String token)throws OAuthException {
        JSONObject checkTokenResult = null;
        try {
            checkTokenResult = new JSONObject((HashMap<String,Object>)tokenEndpoint.checkToken(token));
            if(null != checkTokenResult){
//                checkTokenResult.put("authorities",null);
                checkTokenResult.remove("authorities");
            }
            YjglUser yjglUser = usersRepository.findByUserNameAndIsSoftDel((String) checkTokenResult.get("user_name"),0);
            if(null != yjglUser && StringUtils.isNotBlank(yjglUser.getRealName())){
                checkTokenResult.put("real_name",yjglUser.getRealName());
            }
        }catch (Exception e){
            if(e instanceof InvalidTokenException){
                throw new OAuthException("token失效或不合法");
            }
        }
        return checkTokenResult;
    }


    /**
     * 生成图片验证码,其他来源不需要输入pc端来源需要输入deviceId
     */
    @ApiOperation("生成图片验证码")
    @GetMapping(value = "/oauth/images/imagecode")
    public void getVerify(HttpServletRequest request, HttpServletResponse response,
                          @RequestParam(value = "userName", required = false) String userName,
                          @RequestParam String client_id) {
        userName = userName.toUpperCase();
        try {
            log.info("==获取验证码===new");
            response.setContentType("image/jpeg");//设置相应类型,告诉浏览器输出的内容为图片
            response.setHeader("Pragma", "No-cache");//设置响应头信息，告诉浏览器不要缓存此内容
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expire", 0);
            ImageCode imageCode =new ImageCode();
            String code = imageCode.getRandcode(request, response);//输出验证码图片方法
            log.info("jt_oauth_code={}",code);
            String redisKey = ConstantUtil.PREFIX_CODE+"_"+client_id+"_imageCode_";
            redisService.putHash(redisKey,userName,code);
        } catch (Exception e) {
            log.error("获取验证码失败>>>>   ", e);
        }
    }

}